/////////////////////////////////////////////////////////////////////////////
// This file is part of the "Java-DAP" project, a Java implementation
// of the OPeNDAP Data Access Protocol.
//
// Copyright (c) 2007 OPeNDAP, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
/////////////////////////////////////////////////////////////////////////////
using System;
using System.IO;
using NDODS.DAP.BaseTypes;

namespace NDODS.DAP.Primitives
{
	
	/// <summary> A helper class for <code>DVector</code>.  It allows <code>DVector</code>,
	/// and by extension, <code>DArray</code> and <code>DList</code>, to use more
	/// efficient primitive types to hold large arrays of data.
	/// A <code>PrimitiveVector</code> class is defined for each
	/// primitive type supported in OPeNDAP, and a
	/// <code>BaseTypePrimitiveVector</code> class handles <code>DArray</code>s
	/// and <code>DList</code>s of compound types.
	/// 
	/// </summary>
	/// <author>  jehamby
	/// </author>
	/// <version>  $Revision: 15901 $
	/// </version>
	/// <seealso cref="BaseType">
	/// </seealso>
	/// <seealso cref="DVector">
	/// </seealso>
	[Serializable]
	abstract public class PrimitiveVector : IClientIO, System.ICloneable
	{
		/// <summary> Returns the template variable for this vector.
		/// 
		/// </summary>
		/// <returns> the template variable for this vector.
		/// </returns>
		/// <seealso cref="Deserialize">
		/// </seealso>
		virtual public BaseType Template
		{
			get
			{
				return var;
			}
			
		}
		//UPGRADE_NOTE: Respective javadoc comments were merged.  It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'"
		/// <summary> Returns the number of elements in the array.
		/// 
		/// </summary>
		/// <returns> the number of elements in the array.
		/// </returns>
		/// <summary> Sets the number of elements in the array.  Allocates a new primitive
		/// array of the desired size.  Note that if this is called multiple times,
		/// the old array and its contents will be lost.
		/// <p/>
		/// Only called inside of <code>Deserialize</code> method or in derived
		/// classes on server.
		/// 
		/// </summary>
		/// <param name="len">the number of elements in the array.
		/// </param>
		abstract public int Length{get;set;}
		//UPGRADE_NOTE: Respective javadoc comments were merged.  It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'"
		/// <summary> Returns (a reference to) the internal storage for PrimitiveVector.
		/// <h2><i>WARNING:</i></h2>
		/// Because this method breaks encapsulation rules the user must beware!
		/// If we (the OPeNDAP prgramming team) choose to change the internal
		/// representation(s) of these types your code will probably break.
		/// <p/>
		/// This method is provided as an optimization to eliminate massive
		/// copying of data.
		/// </summary>
		/// <summary> Set the internal storage for PrimitiveVector.
		/// <h2><i>WARNING:</i></h2>
		/// Because this method breaks encapsulation rules the user must beware!
		/// If we (the OPeNDAP prgramming team) choose to change the internal
		/// representation(s) of these types your code will probably break.
		/// <p/>
		/// This method is provided as an optimization to eliminate massive
		/// copying of data.
		/// </summary>
		abstract public System.Object InternalStorage{get;set;}
		
		internal const long serialVersionUID = 1;
		
		/// <summary> Template variable to use for <code>PrintDeclaration</code> and
		/// <code>Deserialize</code> (<code>BaseTypePrimitiveVector</code> only).
		/// </summary>
		private BaseType var;
		
		/// <summary> Constructs a new <code>PrimitiveVector</code>.
		/// 
		/// </summary>
		/// <param name="var">the template <code>BaseType</code> to use.
		/// </param>
		public PrimitiveVector(BaseType var)
		{
			this.var = var;
		}
		
		/// <summary> Returns a clone of this <code>PrimitiveVector</code>.  A deep copy is
		/// performed on all data inside the variable.
		/// 
		/// </summary>
		/// <returns> a clone of this <code>PrimitiveVector</code>.
		/// </returns>
		public virtual System.Object Clone()
		{
			try
			{
				PrimitiveVector v = (PrimitiveVector) base.MemberwiseClone();
				v.var = (BaseType) var.Clone();
				return v;
			}
			//UPGRADE_NOTE: Exception 'java.lang.CloneNotSupportedException' was converted to 'System.Exception' which has different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1100'"
			catch (System.Exception e)
			{
				// this shouldn't happen, since we are Cloneable
				throw new System.ApplicationException();
			}
		}
		
		/// <summary> Reads data from a <code>DataInputStream</code>. This method is only used
		/// on the client side of the OPeNDAP client/server connection.
		/// 
		/// </summary>
		/// <param name="source">  a <code>DataInputStream</code> to Read from.
		/// </param>
		/// <param name="sv">      The <code>ServerVersion</code> returned by the server.
		/// (used by <code>DSequence</code> to determine which protocol version was
		/// used).
		/// </param>
		/// <param name="statusUI">The <code>StatusUI</code> object to use for GUI updates
		/// and user cancellation notification (may be null).
		/// </param>
		/// <throws>  DataReadException when invalid data is Read, or if the user </throws>
		/// <summary>                           cancels the download.
		/// </summary>
		/// <throws>  EOFException      if EOF is found before the variable is completely </throws>
		/// <summary>                           deserialized.
		/// </summary>
		/// <throws>  IOException       thrown on any other InputStream exception. </throws>
		/// <seealso cref="ClientIO.deserialize(DataInputStream, ServerVersion, StatusUI)">
		/// </seealso>
		//UPGRADE_TODO: Class 'java.io.DataInputStream' was converted to 'System.IO.BinaryReader' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataInputStream'"
		abstract public void  Deserialize(System.IO.BinaryReader source, ServerVersion sv, IStatusUI statusUI);
		
		/// <summary> Writes data to a <code>DataOutputStream</code>. This method is used
		/// primarily by GUI clients which need to download OPeNDAP data, manipulate
		/// it, and then re-save it as a binary file.
		/// 
		/// </summary>
		/// <param name="sink">a <code>DataOutputStream</code> to write to.
		/// </param>
		/// <throws>  IOException thrown on any <code>OutputStream</code> </throws>
		/// <summary>                     exception.
		/// </summary>
		//UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
		abstract public void  Externalize(System.IO.BinaryWriter sink);
		
		/// <summary> Write a subset of the data to a <code>DataOutputStream</code>.
		/// 
		/// </summary>
		/// <param name="sink">a <code>DataOutputStream</code> to write to.
		/// </param>
		/// <param name="start:">starting index (i=start)
		/// </param>
		/// <param name="stop:">ending index (i<=stop)
		/// </param>
		/// <param name="stride:">index stride (i+=stride)
		/// </param>
		/// <exception cref="IOException">thrown on any <code>OutputStream</code> exception.
		/// </exception>
		// abstract public void Externalize(DataOutputStream sink, int start, int stop, int stride) throws IOException;
		
		
		/// <summary> Write the variable's declaration in a C-style syntax. This
		/// method is used to create textual representation of the Data
		/// Descriptor Structure (DDS).
		/// 
		/// </summary>
		/// <param name="os">         The <code>StreamWriter</code> on which to Print the
		/// declaration.
		/// </param>
		/// <param name="space">      Each line of the declaration will begin with the
		/// characters in this string.  Usually used for leading spaces.
		/// </param>
		/// <param name="Print_semi"> a bool value indicating whether to Print a
		/// semicolon at the end of the declaration.
		/// </param>
		/// <param name="constrained">a bool value indicating whether to Print
		/// the declartion dependent on the projection information. <b>This
		/// is only used by Server side code.</b>
		/// </param>
		/// <seealso cref="BaseType.printDecl(StreamWriter, String, bool, bool)">
		/// </seealso>
		public void  printDecl(System.IO.StreamWriter os, System.String space, bool print_semi, bool constrained)
		{
			
			//os.println("PrimitiveVector.PrintDeclaration()");
			//os.println(var.getTypeName()+".isProject():"+((ServerMethods)var).isProject());
			var.PrintDeclaration(os, space, print_semi, constrained);
		}
		
		/// <summary> Write the variable's declaration in a C-style syntax. This
		/// method is used to create textual representation of the Data
		/// Descriptor Structure (DDS).
		/// 
		/// </summary>
		/// <param name="os">        The <code>StreamWriter</code> on which to Print the
		/// declaration.
		/// </param>
		/// <param name="space">     Each line of the declaration will begin with the
		/// characters in this string.  Usually used for leading spaces.
		/// </param>
		/// <param name="Print_semi">a bool value indicating whether to Print a
		/// semicolon at the end of the declaration.
		/// </param>
		/// <seealso cref="BaseType.printDecl(StreamWriter, String, bool)">
		/// </seealso>
		public void  printDecl(System.IO.StreamWriter os, System.String space, bool print_semi)
		{
			printDecl(os, space, print_semi, false);
		}
		
		/// <summary> Prints the value of all variables in this vector.  This
		/// method is primarily intended for debugging OPeNDAP applications and
		/// text-based clients such as geturl.
		/// 
		/// </summary>
		/// <param name="os">   the <code>StreamWriter</code> on which to Print the value.
		/// </param>
		/// <param name="space">this value is passed to the <code>PrintDeclaration</code> method,
		/// and controls the leading spaces of the output.
		/// </param>
		/// <seealso cref="BaseType.printVal(StreamWriter, String, bool)">
		/// </seealso>
		abstract public void  printVal(System.IO.StreamWriter os, System.String space);
		
		/// <summary> Prints the value of a single variable in this vector.
		/// method is used by <code>DArray</code>'s <code>PrintValue</code> method.
		/// 
		/// </summary>
		/// <param name="os">   the <code>StreamWriter</code> on which to Print the value.
		/// </param>
		/// <param name="index">the index of the variable to Print.
		/// </param>
		/// <seealso cref="DArray.printVal(StreamWriter, String, bool)">
		/// </seealso>
		abstract public void  printSingleVal(System.IO.StreamWriter os, int index);
		
		/// <summary> Create a new primitive vector using a subset of the data.
		/// 
		/// </summary>
		/// <param name="start"> starting index (i=start)
		/// </param>
		/// <param name="stop">  ending index (i<=stop)
		/// </param>
		/// <param name="stride">index stride (i+=stride)
		/// </param>
		/// <returns> new primitive vector
		/// </returns>
		abstract public PrimitiveVector subset(int start, int stop, int stride);
	}
}